package codename.carrot.bomberman.adapters;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import codename.carrot.bomberman.AppStorage;
import codename.carrot.bomberman.LevelDefinition;
import codename.carrot.bomberman.R;
import codename.carrot.bomberman.activity.LevelViewerActivity;
import codename.carrot.bomberman.game.networkobjects.DroidPoint;
import codename.carrot.bomberman.game.networkobjects.ItemContainer;

/**
 *  An adapter for levels, compatable for use by a {@link Gallery}, or {@link ImageSwitcher}
 * @author Group A4
 * @see LevelViewerActivity
 * 
 */
public class LevelAdapter extends ArrayAdapter<LevelDefinition> {

	/**
	 * The calling context/activity.
	 */
    private Context context;
    /**
     * Layout inflator for setting up and updating the GUI.
     */
	private LayoutInflater inflater;

	/**
	 * Constructs a Level adapter and setting up the level inflator.
	 * @param context The calling context.
	 * @param resource The resource ID for a layout file containing a TextView to use when instantiating views.
	 * @param textViewResourceId The id of the TextView within the layout resource to be populated.
	 */
	public LevelAdapter(Context context, int resource, int textViewResourceId) {
		super(context, resource, textViewResourceId);
		this.context = context;
		inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	}

	/**
	 * Setting the GUI-component to be displayed (view) and returning it.
	 * @see android.widget.ArrayAdapter#getView(int position, View convertView, ViewGroup parent)
	 */
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {	    
	    View v;	    
	    
	    if(convertView == null) {
	        v = inflater.inflate(R.layout.level_item, null);
	    }
	    else {
	        v = convertView;
	    }	    	   
	    
		LevelDefinition level = getItem(position);				
		ImageView iv = (ImageView) v.findViewById(R.id.ivLevel);
		Bitmap b = getDrawnLevel(level,AppStorage.SCREEN_WIDTH, AppStorage.SCREEN_HEIGHT);
		iv.setImageBitmap(b);
		return v;
	}
	

	/**
	 * Generates a Bitmap to view a picture for the specific level.
	 *
	 * @param level The level to draw.
	 * @param canvasWidth The height of the canvas to be drawn.
	 * @param canvasHeight The width of the canvas to be drawn.
	 * @return A bitmap view of the level.
	 */
	private Bitmap getDrawnLevel(LevelDefinition level, int canvasWidth, int canvasHeight) {
	    int height = level.getHeight();
	    int width = level.getWidth();
	    
	    int tileSize = Math.min(canvasWidth,  canvasHeight) / Math.max(height, width);
	    canvasWidth = tileSize*width;
	    canvasHeight = tileSize*height;
	    
	    Paint tilePaint = new Paint();
	    Paint levelNamePaint = new Paint();
	    levelNamePaint.setColor(Color.WHITE);
	    levelNamePaint.setTextSize(30);
	    Bitmap boulderBitmap = getScaledBitmap(tileSize, R.drawable.boulder);
	    Bitmap itemContainerBitmap = getScaledBitmap(tileSize, R.drawable.crate);
	    Bitmap grassBitmap = getScaledBitmap(tileSize, R.drawable.grass);	    	   
	    
	    String levelText = level.getName();
	    Rect textRect = 	new Rect();
	    levelNamePaint.getTextBounds(levelText, 0, levelText.length(), textRect);	    
	    int offsetY = textRect.height();	    
	    	    
	       // height and width MUST fit in the gallery
        Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
        Bitmap bmp = Bitmap.createBitmap(canvasWidth, canvasHeight+offsetY, conf); // this creates a MUTABLE bitmap
        Canvas canvas = new Canvas(bmp);
	    	   
       for(int x=0; x < width; x++) {
            for(int y=0; y < height; y++) {
                canvas.drawBitmap(grassBitmap, x*tileSize, y*tileSize+offsetY, tilePaint);
            }
        }
	    for(DroidPoint p : level.getBoulders()) {	       
	        canvas.drawBitmap(boulderBitmap, p.x*tileSize, p.y*tileSize+offsetY, tilePaint);
	    }	    
	    for(ItemContainer i : level.getItemContainers()) {
	        DroidPoint dp = i.getDroidPoint();
	        canvas.drawBitmap(itemContainerBitmap, dp.x*tileSize, dp.y*tileSize+offsetY, tilePaint);
	    }	   
	    
	    canvas.drawText(levelText, 0, offsetY, levelNamePaint);
	    
	    // Draw the starting positions	
	    DroidPoint dpBlue = level.getStartPos(LevelDefinition.COLOR_BLUE);
	    DroidPoint dpOrange = level.getStartPos(LevelDefinition.COLOR_ORANGE);
	    DroidPoint dpYellow = level.getStartPos(LevelDefinition.COLOR_YELLOW);
	    DroidPoint dpPurple = level.getStartPos(LevelDefinition.COLOR_PURPLE);
	    
	    Bitmap blue = getScaledBitmap(tileSize, R.drawable.blue_1_d);
	    Bitmap orange = getScaledBitmap(tileSize, R.drawable.orange_1_d);
	    Bitmap yellow = getScaledBitmap(tileSize, R.drawable.yellow_1_d);
	    Bitmap purple = getScaledBitmap(tileSize, R.drawable.purpel_1_d);	    	    
	    
	    drawStartPos(dpBlue, blue, tileSize, offsetY, canvas);
	    drawStartPos(dpOrange, orange, tileSize, offsetY, canvas);
	    drawStartPos(dpYellow, yellow, tileSize, offsetY, canvas);
	    drawStartPos(dpPurple, purple, tileSize, offsetY, canvas);
	    
	    return bmp;
	}	
	
	/**
	 * Draws the spart position of each player on the map.
	 * @param pos The posititon to draw on.
	 * @param playerBitmap A image representation a player.
	 * @param tileSize The size of the tile to draw.
	 * @param offsetY The offset.
	 * @param canvas The canvas to draw on.
	 */
	private void drawStartPos(DroidPoint pos, Bitmap playerBitmap, int tileSize, int offsetY,Canvas canvas) {
	    Paint paint = new Paint();
	    canvas.drawBitmap(playerBitmap, pos.x*tileSize, pos.y*tileSize+offsetY, paint);
	}
	
	/**
	 * Scales the bitmap of the level.
	 * @param size The size to scale to.
	 * @param resource The resource to scale (drawable resource).
	 * @return A scaled bitmap.
	 */
	private Bitmap getScaledBitmap(int size, int resource) {
	    Drawable drawable = context.getResources().getDrawable(resource);
	    Bitmap bb = ((BitmapDrawable) drawable).getBitmap();
	    
	    int width = bb.getWidth();
	    int height = bb.getHeight();
	    
	    float scaleWidth = ((float) size / width);
	    float scaleHeight = ((float) size / height);
	    
	    Matrix matrix = new Matrix();
	    matrix.postScale(scaleWidth, scaleHeight);
	    
	    Bitmap resultBitmap = Bitmap.createBitmap(bb, 0, 0, width, height, matrix, true); 
	    return resultBitmap;
	}	
}
